/*
 * $Header: PlayerClass.java, 24/11/2005 12:56:01 luisantonioa Exp $
 *
 * $Author: luisantonioa $
 * $Date: 24/11/2005 12:56:01 $
 * $Revision: 1 $
 * $Log: PlayerClass.java,v $
 * Revision 1  24/11/2005 12:56:01  luisantonioa
 * Added copyright notice
 *
 *
 * This program is free software: you can redistribute it and/or modify it under
 * the terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 * 
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
 * details.
 * 
 * You should have received a copy of the GNU General Public License along with
 * this program. If not, see <http://www.gnu.org/licenses/>.
 */
package com.l2jserver.gameserver.model.base;

import static com.l2jserver.gameserver.model.base.ClassLevel.First;
import static com.l2jserver.gameserver.model.base.ClassLevel.Fourth;
import static com.l2jserver.gameserver.model.base.ClassLevel.Second;
import static com.l2jserver.gameserver.model.base.ClassLevel.Third;
import static com.l2jserver.gameserver.model.base.ClassType.Fighter;
import static com.l2jserver.gameserver.model.base.ClassType.Mystic;
import static com.l2jserver.gameserver.model.base.ClassType.Priest;
import static com.l2jserver.gameserver.model.base.Race.DarkElf;
import static com.l2jserver.gameserver.model.base.Race.Dwarf;
import static com.l2jserver.gameserver.model.base.Race.Elf;
import static com.l2jserver.gameserver.model.base.Race.Human;
import static com.l2jserver.gameserver.model.base.Race.Kamael;
import static com.l2jserver.gameserver.model.base.Race.Orc;

import java.util.EnumMap;
import java.util.EnumSet;
import java.util.Set;

import com.l2jserver.Config;
import com.l2jserver.gameserver.model.actor.instance.L2PcInstance;


/**
 * This class ...
 *
 * @version $Revision: 1.2 $ $Date: 2004/06/27 08:12:59 $
 */
public enum PlayerClass
{
	휴먼파이터(Human, Fighter, First),
	워리워(Human, Fighter, Second),
	글라디에이터(Human, Fighter, Third),
	워로드(Human, Fighter, Third),
	휴먼나이트(Human, Fighter, Second),
	팔라딘(Human, Fighter, Third),
	다크어벤져(Human, Fighter, Third),
	로그(Human, Fighter, Second),
	트레져헌터(Human, Fighter, Third),
	호크아이(Human, Fighter, Third),
	휴먼메이지(Human, Mystic, First),
	휴먼위자드(Human, Mystic, Second),
	소서러(Human, Mystic, Third),
	네크로멘서(Human, Mystic, Third),
	워록(Human, Mystic, Third),
	클레릭(Human, Priest, Second),
	비숍(Human, Priest, Third),
	프로핏(Human, Priest, Third),
	
	엘프파이터(Elf, Fighter, First),
	엘프나이트(Elf, Fighter, Second),
	템플나이트(Elf, Fighter, Third),
	소드싱어(Elf, Fighter, Third),
	스카우트(Elf, Fighter, Second),
	플레인워커(Elf, Fighter, Third),
	실버레인저(Elf, Fighter, Third),
	엘프메이지(Elf, Mystic, First),
	엘프위자드(Elf, Mystic, Second),
	스펠싱어(Elf, Mystic, Third),
	엘리멘탈서머너(Elf, Mystic, Third),
	오라클(Elf, Priest, Second),
	엘더(Elf, Priest, Third),
	
	다크파이터(DarkElf, Fighter, First),
	팰러스나이트(DarkElf, Fighter, Second),
	실리엔나이트(DarkElf, Fighter, Third),
	블레이드댄서(DarkElf, Fighter, Third),
	어쎄신(DarkElf, Fighter, Second),
	어비스워커(DarkElf, Fighter, Third),
	팬텀레인져(DarkElf, Fighter, Third),
	다크메이지(DarkElf, Mystic, First),
	다크위저드(DarkElf, Mystic, Second),
	스펠하울러(DarkElf, Mystic, Third),
	팬텀서머너(DarkElf, Mystic, Third),
	실리엔오라클(DarkElf, Priest, Second),
	실리엔엘더(DarkElf, Priest, Third),
	
	오크파이터(Orc, Fighter, First),
	레이더(Orc, Fighter, Second),
	디스트로이어(Orc, Fighter, Third),
	몽크(Orc, Fighter, Second),
	타이런트(Orc, Fighter, Third),
	오크메이지(Orc, Mystic, First),
	오크샤먼(Orc, Mystic, Second),
	오버로드(Orc, Mystic, Third),
	워크라이어(Orc, Mystic, Third),
	
	드워프파이터(Dwarf, Fighter, First),
	스케빈져(Dwarf, Fighter, Second),
	바운티헌터(Dwarf, Fighter, Third),
	아티산(Dwarf, Fighter, Second),
	워스미스(Dwarf, Fighter, Third),
	
	dummyEntry1(null, null, null),
	dummyEntry2(null, null, null),
	dummyEntry3(null, null, null),
	dummyEntry4(null, null, null),
	dummyEntry5(null, null, null),
	dummyEntry6(null, null, null),
	dummyEntry7(null, null, null),
	dummyEntry8(null, null, null),
	dummyEntry9(null, null, null),
	dummyEntry10(null, null, null),
	dummyEntry11(null, null, null),
	dummyEntry12(null, null, null),
	dummyEntry13(null, null, null),
	dummyEntry14(null, null, null),
	dummyEntry15(null, null, null),
	dummyEntry16(null, null, null),
	dummyEntry17(null, null, null),
	dummyEntry18(null, null, null),
	dummyEntry19(null, null, null),
	dummyEntry20(null, null, null),
	dummyEntry21(null, null, null),
	dummyEntry22(null, null, null),
	dummyEntry23(null, null, null),
	dummyEntry24(null, null, null),
	dummyEntry25(null, null, null),
	dummyEntry26(null, null, null),
	dummyEntry27(null, null, null),
	dummyEntry28(null, null, null),
	dummyEntry29(null, null, null),
	dummyEntry30(null, null, null),
	/*
	 * (3rd classes)
	 */
	듀얼리스트(Human, Fighter, Fourth),
	드레드노트(Human, Fighter, Fourth),
	피닉스나이트(Human, Fighter, Fourth),
	헬나이트(Human, Fighter, Fourth),
	사지타리우스(Human, Fighter, Fourth),
	어드벤쳐러(Human, Fighter, Fourth),
	아크메이지(Human, Mystic, Fourth),
	소울테이커(Human, Mystic, Fourth),
	아르카나로드(Human, Mystic, Fourth),
	카디날(Human, Priest, Fourth),
	하이로펀트(Human, Priest, Fourth),
	
	에바스템플러(Elf, Fighter, Fourth),
	소드뮤즈(Elf, Fighter, Fourth),
	윈드라이더(Elf, Fighter, Fourth),
	문라이트센티넬(Elf, Fighter, Fourth),
	미스틱뮤즈(Elf, Mystic, Fourth),
	엘리멘탈마스터(Elf, Mystic, Fourth),
	에바스세인트(Elf, Priest, Fourth),
	
	실리엔템플러(DarkElf, Fighter, Fourth),
	스펙트럴댄서(DarkElf, Fighter, Fourth),
	고스트헌터(DarkElf, Fighter, Fourth),
	고스트센티넬(DarkElf, Fighter, Fourth),
	스톰스크리머(DarkElf, Mystic, Fourth),
	스펙트럴마스터(DarkElf, Mystic, Fourth),
	실리엔세인트(DarkElf, Priest, Fourth),
	
	타이탄(Orc, Fighter, Fourth),
	그랜드카다바리(Orc, Fighter, Fourth),
	도미네이터(Orc, Mystic, Fourth),
	둠크라이어(Orc, Mystic, Fourth),
	
	표춘씨커(Dwarf, Fighter, Fourth),
	마에스트로(Dwarf, Fighter, Fourth),
	
	dummyEntry31(null, null, null),
	dummyEntry32(null, null, null),
	dummyEntry33(null, null, null),
	dummyEntry34(null, null, null),
	
	남솔져(Kamael, Fighter, First),
	여솔져(Kamael, Fighter, First),
	트루퍼(Kamael, Fighter, Second),
	워더(Kamael, Fighter, Second),
	버서커(Kamael, Fighter, Third),
	남소울브레커(Kamael, Fighter, Third),
	여소울브레커(Kamael, Fighter, Third),
	아바레스터(Kamael, Fighter, Third),
	둠브링거(Kamael, Fighter, Fourth),
	남소울하운드(Kamael, Fighter, Fourth),
	여소울하운드(Kamael, Fighter, Fourth),
	트릭스터(Kamael, Fighter, Fourth),
	인스펙터(Kamael, Fighter, Third),
	쥬디케이터(Kamael, Fighter, Fourth);
	
	private Race _race;
	private ClassLevel _level;
	private ClassType _type;
	
	private static final Set<PlayerClass> mainSubclassSet;
	private static final Set<PlayerClass> neverSubclassed = EnumSet.of(오버로드, 워스미스);
	
	private static final Set<PlayerClass> subclasseSet1 = EnumSet.of(다크어벤져, 팔라딘, 템플나이트, 실리엔나이트);
	private static final Set<PlayerClass> subclasseSet2 = EnumSet.of(트레져헌터, 어비스워커, 플레인워커);
	private static final Set<PlayerClass> subclasseSet3 = EnumSet.of(호크아이, 실버레인저, 팬텀레인져);
	private static final Set<PlayerClass> subclasseSet4 = EnumSet.of(워록, 엘리멘탈서머너, 팬텀서머너);
	private static final Set<PlayerClass> subclasseSet5 = EnumSet.of(소서러, 스펠싱어, 스펠하울러);
	
	private static final EnumMap<PlayerClass, Set<PlayerClass>> subclassSetMap = new EnumMap<PlayerClass, Set<PlayerClass>>(PlayerClass.class);
	
	static
	{
		Set<PlayerClass> subclasses = getSet(null, Third);
		subclasses.removeAll(neverSubclassed);
		
		mainSubclassSet = subclasses;
		
        subclassSetMap.put(다크어벤져, subclasseSet1);
        subclassSetMap.put(팔라딘, subclasseSet1);
        subclassSetMap.put(템플나이트, subclasseSet1);
        subclassSetMap.put(실리엔나이트, subclasseSet1);

        subclassSetMap.put(트레져헌터, subclasseSet2);
        subclassSetMap.put(어비스워커, subclasseSet2);
        subclassSetMap.put(플레인워커, subclasseSet2);

        subclassSetMap.put(호크아이, subclasseSet3);
        subclassSetMap.put(실버레인저, subclasseSet3);
        subclassSetMap.put(팬텀레인져, subclasseSet3);

        subclassSetMap.put(워록, subclasseSet4);
        subclassSetMap.put(엘리멘탈서머너, subclasseSet4);
        subclassSetMap.put(팬텀서머너, subclasseSet4);

        subclassSetMap.put(소서러, subclasseSet5);
        subclassSetMap.put(스펠싱어, subclasseSet5);
        subclassSetMap.put(스펠하울러, subclasseSet5);
	}
	
	PlayerClass(Race pRace, ClassType pType, ClassLevel pLevel)
	{
		_race = pRace;
		_level = pLevel;
		_type = pType;
	}
	
	public final Set<PlayerClass> getAvailableSubclasses(L2PcInstance player)
	{
		Set<PlayerClass> subclasses = null;
		
		if (_level == Third)
		{
			if (player.getRace() != Kamael)
			{
				subclasses = EnumSet.copyOf(mainSubclassSet);
				
				subclasses.remove(this);
				
				switch (player.getRace())
				{
					case Elf:
						subclasses.removeAll(getSet(DarkElf, Third));
						break;
					case DarkElf:
						subclasses.removeAll(getSet(Elf, Third));
						break;
				}
				
				subclasses.removeAll(getSet(Kamael, Third));
				
				Set<PlayerClass> unavailableClasses = subclassSetMap.get(this);
				
				if (unavailableClasses != null)
					subclasses.removeAll(unavailableClasses);
				
			}
			else
			{
				subclasses = getSet(Kamael, Third);
				subclasses.remove(this);
				// Check sex, male subclasses female and vice versa
				// If server owner set MaxSubclass > 3 some kamael's cannot take 4 sub
				// So, in that situation we must skip sex check
				if (Config.MAX_SUBCLASS <= 3)
				{
					if (player.getAppearance().getSex())
						subclasses.removeAll(EnumSet.of(남소울브레커));
					else
						subclasses.removeAll(EnumSet.of(여소울브레커));
				}
				if (player.getTotalSubClasses() < 2)
					subclasses.removeAll(EnumSet.of(인스펙터));
			}
		}
		return subclasses;
	}
	
	public static final EnumSet<PlayerClass> getSet(Race race, ClassLevel level)
	{
		EnumSet<PlayerClass> allOf = EnumSet.noneOf(PlayerClass.class);
		
		for (PlayerClass playerClass : EnumSet.allOf(PlayerClass.class))
		{
			if (race == null || playerClass.isOfRace(race))
			{
				if (level == null || playerClass.isOfLevel(level))
				{
					allOf.add(playerClass);
				}
			}
		}
		
		return allOf;
	}
	
	public final boolean isOfRace(Race pRace)
	{
		return _race == pRace;
	}
	
	public final boolean isOfType(ClassType pType)
	{
		return _type == pType;
	}
	
	public final boolean isOfLevel(ClassLevel pLevel)
	{
		return _level == pLevel;
	}
	
	public final ClassLevel getLevel()
	{
		return _level;
	}
}